import { assert, AudioClip, AudioSource, director, instantiate, Node, Prefab, resources } from "cc";
import { Epath, EprefabName, GAME_SAVING_KEY } from "./Config";
import { PlayerData } from "../game/PlayerData";

export class EventCenter {
    private _event: [id: number, callback: Function, target: any][] = [];

    on(id: number, callback: Function, target: any) {
        let index = this._event.findIndex(([i, c, t]) => i == id && c == callback && t == target);
        if (index == -1) {
            this._event.push([id, callback, target]);
        }
    }
    off(id: number, callback: Function, target: any) {
        let index = this._event.findIndex(([i, c, t]) => i == id && c == callback && t == target);
        if (index != -1) {
            this._event.splice(index, 1);
        }
    }
    emit(id: number, ...args: any[]) {
        this._event.forEach(e => {
            if (e[0] == id) {
                e[1]?.apply(e[2], args);
            }
        });
    }

}

//声音
export class AudioManager {
    private static _instance: AudioManager;
    //单例模式
    public static get instance(): AudioManager {
        if (!this._instance) {
            this._instance = new AudioManager();
        }
        return this._instance;
    }

    private _audioCaches: Record<string, AudioClip> = {};
    private _audioSource: AudioSource;

    private constructor() {

    }
    init(audioSource: AudioSource) {
        this._audioSource = audioSource;
    }
    //播放音效
    playSound(name: string, volume: number = 1.0) {
        if (!this._audioSource) {
            console.warn('_audioSource是空');
            return;
        }
        let url = Epath.AUDIO_SOUND + name;
        if (this._audioCaches[url]) {
            //音效只播放一次
            this._audioSource.playOneShot(this._audioCaches[url], volume);
        } else {
            resources.load(url, (err, audioClip) => {
                if (err) {
                    console.log(err);
                    return;
                }
                this._audioCaches[url] = audioClip as AudioClip;
                this._audioSource.playOneShot(this._audioCaches[url], volume);
            });
        }
    }
    //播放音乐 
    playMusic(name: string, volume: number = 1.0) {
        if (!this._audioSource) {
            console.warn('_audioSource是空');
            return;
        }
        let url = Epath.AUDIO_MUSIC + name;
        if (this._audioCaches[url]) {
            //音乐需要循环播放
            this._audioSource.clip = this._audioCaches[url];
            this._audioSource.volume = volume;
            this._audioSource.loop = true;
            this._audioSource.play();
        } else {
            resources.load(url, (err, audioClip) => {
                if (err) {
                    console.log(err);
                    return;
                }
                this._audioCaches[url] = audioClip as AudioClip;
                this._audioSource.clip = this._audioCaches[url];
                this._audioSource.volume = volume;
                this._audioSource.loop = true;
                this._audioSource.play();
            });
        }
    }
}

function saveToLocal(data:{}){
    //保存数据到本地
    try {
        let jsonData = JSON.stringify(data);
        localStorage.setItem(GAME_SAVING_KEY,jsonData);
    }catch (e) {
        console.warn('保存数据失败',e);
    }
}
function loadFromLocal(): {}{
    //从本地读取数据
    try{
        let data=localStorage.getItem(GAME_SAVING_KEY);
        if(data&&data.length>0){
            return JSON.parse(data);
        }
    }catch (e) {
        console.warn('读取数据失败',e);
    }
    return null;
}

export class Core {
    private static _instance: Core;
    //单例模式
    public static get instance(): Core {
        if (!this._instance) {
            this._instance = new Core();
        }
        return this._instance;
    }

    private constructor() {

    }
    //预制体缓存
    private _prefabCache: Record<string, Prefab> = {};

    playerData: PlayerData = new PlayerData();
    event: EventCenter = new EventCenter();

    init(onFinished?:()=>void) {

        let perisitNode=new Node('AudioSourceNode');
        director.getScene().addChild(perisitNode);
        director.addPersistRootNode(perisitNode);
        AudioManager.instance.init(perisitNode.addComponent(AudioSource));

        let data=loadFromLocal();
        if(data){
            //加载本地数据
            console.log('老用户');
            this.playerData.setPackage(data);
        }else{
            //初始化数据
            console.log('新用户');
        }
        console.log('用户数据是:',this.playerData)

        let tasks: Promise<void>[] = [];
        Object.keys(EprefabName).forEach(key => {
            let name = EprefabName[key];
            let url = Epath.PREFAB_PATH + name;
            let task=new Promise<void>((resove,reject)=>{
                resources.load(url, (err, prefab) => {
                    if (err) {
                        console.log(err);
                        reject();
                        return;
                    }
                    this._prefabCache[name] = prefab as Prefab;
                    resove();
                });
            });
            tasks.push(task);
        });
        Promise.all(tasks).then(()=>{
            console.log('init success');
            onFinished?.();
        });
    }

    // 创建节点
    creatNode(name: string, parent?: Node): Node {
        let prefab = this._prefabCache[name];
        if (!prefab) {
            console.log('节点不存在', name);
            return null;
        }
        let node = instantiate(prefab);
        node.parent = parent;
        return node;
    }
    save(){
        saveToLocal(this.playerData.getPackage());
    }
}